using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;

public class EffectMgr : SingletonMono<EffectMgr>
{
    // effect pool
    private PoolMgr<Effect> _effectPool;
    //effect cfg
    private Dictionary<int, EffectConfigItem> _effectCfg = new Dictionary<int, EffectConfigItem>();
    // playing effect list
    private List<Effect> _playingEffect;
    //remove effect list
    private List<Effect> _removeEffect;
    //缓存池 加载过的特效路径
    private List<string> _cachePath = new List<string>();
    
    public override void Init(){
        base.Init();
        // load effect config
        _effectCfg = new Dictionary<int, EffectConfigItem>();
        _playingEffect = new List<Effect>();
        _removeEffect = new List<Effect>();
        _effectPool = PoolMgr<Effect>.Instance;
        LoadEffectConfig();
    }

    private async void LoadEffectConfig()
    {
        string asset_path = "Assets/Scripts/Effect/EffectConfig.asset";
        var config = await LoadMgr.Instance.LoadAsset<EffectConfig>(asset_path);
        foreach (var item in config.items)
        {
            _effectCfg.Add(item.id, item);
        }
    }

    void Update()
    {
        foreach (var effect in _playingEffect)
        {
            effect.Refresh();

            if(effect.IsEnd)
            {
                _removeEffect.Add(effect);
            }
        }

        
        if(_removeEffect.Count > 0)
        {
            foreach(var item in _removeEffect)
            {
                _playingEffect.Remove(item);
                _effectPool.Put(item.GetEffectName(),item);
            }

            _removeEffect.Clear();
        }


    }

    //播放世界特效
    public async UniTask<Effect> PlayWorldEffect(int id,Vector3 pos = default(Vector3),float scale = 1,Action<Effect> begin = null,Action<Effect> end = null)
    {
        EffectConfigItem cfg = GetEffectConfig(id);
        if (cfg == null)
        {
            Debug.LogError("EffectMgr.PlayEffect: effect config is null, id = " + id);
            return null;
        }
        Effect effect = await GetEffect(id);
        // if (effect == null)
        // {
        //     effect = await CreateEffect(id);
        // }
        // effect.delayCallback = callback;
        effect.Init(cfg);
        effect.BeginCallback = begin;
        effect.EndCallback = end;
        effect.SetPosition(pos);
        effect.Play();
        _playingEffect.Add(effect);
        return effect;
    }

    //播放绑点特效
    public async UniTask<Effect> PlayBindEffect(int id,Transform target,float scale = 1,Action<Effect> begin = null,Action<Effect> end = null)
    {
        EffectConfigItem cfg = GetEffectConfig(id);
        if (cfg == null)
        {
            Debug.LogError("EffectMgr.PlayEffect: effect config is null, id = " + id);
            return null;
        }
        Effect effect = _effectPool.Get(cfg.name);
        if (effect == null)
        {
            effect = await GetEffect(id);
        }
        effect.Init(cfg);
        effect.BeginCallback = begin;
        effect.EndCallback = end;
        effect.SetTarget(target);
        // effect.SetPosition(pos);
        effect.Play();
        _playingEffect.Add(effect);
        return effect;
    }

    // get effect config
    public EffectConfigItem GetEffectConfig(int id)
    {
        EffectConfigItem cfg = null;
        if (_effectCfg.TryGetValue(id,out cfg))
        {
            return cfg;
        }
        return null;
    }

    //create effect by cfg

    public async UniTask<Effect> GetEffect(int id)
    {
        var cfg = GetEffectConfig(id);
        // var ins = await LoadMgr.Instance.Instantiate(cfg.path);

        var effect = await LoadMgr.Instance.LoadInstance<Effect>(cfg.path);
        //缓存池是否存在路径
        if (!_cachePath.Contains(cfg.name))
        {
            _cachePath.Add(cfg.name);
        }
        return effect;
    }

    public override void Clean()
    {
        base.Clean();

        foreach (var item in _playingEffect)
        {
            item.Stop();
            _removeEffect.Add(item);
        }
        _playingEffect.Clear();
        foreach(var item in _removeEffect)
        {
            _playingEffect.Remove(item);
            _effectPool.Put(item.GetEffectName(),item);
        }

        _removeEffect.Clear();
        foreach (var item in _cachePath)
        {
            _effectPool.Clean(item);
        }

        _cachePath.Clear();
    }

}